(function(define) {
'use strict';
define('video/09_save_state_plugin.js', [], function() {
    /**
     * Save state module.
     * @exports video/09_save_state_plugin.js
     * @constructor
     * @param {Object} state The object containing the state of the video
     * @param {Object} i18n The object containing strings with translations.
     * @param {Object} options
     * @return {jquery Promise}
     */
    var SaveStatePlugin = function(state, i18n, options) {
        if (!(this instanceof SaveStatePlugin)) {
            return new SaveStatePlugin(state, i18n, options);
        }

        _.bindAll(this, 'onSpeedChange', 'saveStateHandler', 'bindUnloadHandler', 'onUnload', 'onYoutubeAvailability',
            'onLanguageChange', 'destroy');
        this.state = state;
        this.options = _.extend({events: []}, options);
        this.state.videoSaveStatePlugin = this;
        this.i18n = i18n;
        this.initialize();

        return $.Deferred().resolve().promise();
    };


    SaveStatePlugin.moduleName = 'SaveStatePlugin';
    SaveStatePlugin.prototype = {
        destroy: function () {
            this.state.el.off(this.events).off('destroy', this.destroy);
            $(window).off('unload', this.onUnload);
            delete this.state.videoSaveStatePlugin;
        },

        initialize: function() {
            this.events = {
                'speedchange': this.onSpeedChange,
                'play': this.bindUnloadHandler,
                'pause destroy': this.saveStateHandler,
                'language_menu:change': this.onLanguageChange,
                'youtube_availability': this.onYoutubeAvailability
            };
            this.bindHandlers();
        },

        bindHandlers: function() {
            if (this.options.events.length) {
                _.each(this.options.events, function (eventName) {
                    var callback;
                    if (_.has(this.events, eventName)) {
                        callback = this.events[eventName];
                        this.state.el.on(eventName, callback);
                    }
                }, this);
            } else {
                this.state.el.on(this.events);
            }
            this.state.el.on('destroy', this.destroy);
        },

        bindUnloadHandler: _.once(function () {
            $(window).on('unload.video', this.onUnload);
        }),

        onSpeedChange: function (event, newSpeed) {
            this.saveState(true, {speed: newSpeed});
            this.state.storage.setItem('speed', newSpeed, true);
            this.state.storage.setItem('general_speed', newSpeed);
        },

        saveStateHandler: function () {
            this.saveState(true);
        },

        onUnload: function () {
            this.saveState();
        },

        onLanguageChange: function (event, langCode) {
            this.state.storage.setItem('language', langCode);
        },

        onYoutubeAvailability: function (event, youtubeIsAvailable) {
            // Compare what the client-side code has determined Youtube
            // availability to be (true/false) vs. what the LMS recorded for
            // this user. The LMS will assume YouTube is available by default.
            if (youtubeIsAvailable !== this.state.config.recordedYoutubeIsAvailable) {
                this.saveState(true, {youtube_is_available: youtubeIsAvailable});
            }
        },

        saveState: function (async, data) {
            if (!($.isPlainObject(data))) {
                data = {
                    saved_video_position: this.state.videoPlayer.currentTime
                };
            }

            if (data.speed) {
                this.state.storage.setItem('speed', data.speed, true);
            }

            if (_.has(data, 'saved_video_position')) {
                this.state.storage.setItem('savedVideoPosition', data.saved_video_position, true);
                data.saved_video_position = Time.formatFull(data.saved_video_position);
            }

            $.ajax({
                url: this.state.config.saveStateUrl,
                type: 'POST',
                async: async ? true : false,
                dataType: 'json',
                data: data
            });
        }
    };

    return SaveStatePlugin;
});
}(RequireJS.define));
